"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

"""
"""
Case Type   : 资源池化
Case Name   : 资源池化场景下, 开启按需回放参数进行备节点failover操作
Create At   : 2024-04-07
Owner       : zhenjinyang
Description :
    1、查看集群状态; expect:集群状态正常
    2、加载ondemand参数; expect:执行成功
    3、重启;
    4、检验参数; expect:执行成功
    5、主节点进行failover
    6、再次查看集群状态
    7、对集群进行start
    8、查看集群状态
    9、ondemand参数为初始状态; expect:执行成功
    10、集群停止; expect:执行成功
    11、原节点进行节点启动; expect:执行成功
    12、参数为初始状态; expect:成功
    13、恢复环境为初始集群状态; expect:成功
Expect      :
    1、集群状态正常
    2、参数加载成功
    3、重启成功，集群状态正常
    4、参数设置成功
    5、原主节点down，备节点升为新主节点
    6、集群状态Degrade
    7、集群启动成功
    8、集群状态正常，原主节点为新备节点，原备节点为新主节
    9、ondemand参数恢复初始状态
    10、集群状态为停止状态
    11、集群启动成功，集群状态正常
    12、查看参数值，为初始状态
    13、恢复环境为初始集群状态：1节点为主节点，2节点为备节点，3节点为备节点
History     :
    1、2024-04-07 创建
"""

import os
import unittest
import time

from yat.test import Node
from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import macro

Primary_SH = CommonSH('PrimaryDbUser')
Primary_ROOTSH = CommonSH('PrimaryRoot')
Standby1_SH = CommonSH('Standby1DbUser')



@unittest.skipIf(1 == Primary_SH.get_node_num(), '单机环境不执行')
class SharedStorage(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.constant = Constant()
        self.com = Common()

        self.s1_comsh = CommonSH('Standby1DbUser')
        self.s2_comsh = CommonSH('Standby2DbUser')
        self.common = Common('Standby1DbUser')
        self.recovery_parse_workers = 'recovery_parse_workers'
        self.recovery_redo_workers = 'recovery_redo_workers'
        self.hot_standby = 'hot_standby'
        self.ss_enable_ondemand_recovery = 'ss_enable_ondemand_recovery'
        self.ss_ondemand_recovery_mem_size = 'ss_ondemand_recovery_mem_size'

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        if "cluster_state   : Normal" in status:
            self.log.info(status + "集群状态正常")
        else:
            stopdn = Primary_SH.exec_cm_ctl('stop')
            self.log.info(stopdn)
            status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
            startdn = Primary_SH.exec_cm_ctl('start')
            self.log.info(startdn)
            self.assertIn(self.constant.cm_start_success_msg, startdn,
                    '拉起集群失败')
            status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
            self.log.info(status)

        self.recovery_parse_workers_default = self.common.show_param(self.recovery_parse_workers)
        self.recovery_redo_workers_default = self.common.show_param(self.recovery_redo_workers)
        self.hot_standby_default = self.common.show_param(self.hot_standby)
        self.ss_enable_ondemand_recovery_default = self.common.show_param(self.ss_enable_ondemand_recovery)
        self.ss_ondemand_recovery_mem_size_default = self.common.show_param(self.ss_ondemand_recovery_mem_size)

    def test_shared_storage(self):
        text = '-----step1:查看集群状态; expect:集群状态正常-----'
        self.log.info(text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)

        text = '-----step2:加载ondemand参数; expect:执行成功-----'
        self.log.info(text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.recovery_parse_workers}=2')
        self.assertTrue(result, '执行失败' + text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.recovery_redo_workers}=2')
        self.assertTrue(result, '执行失败' + text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.hot_standby}=off')
        self.assertTrue(result, '执行失败' + text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.ss_enable_ondemand_recovery}=on')
        self.assertTrue(result, '执行失败' + text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.ss_ondemand_recovery_mem_size}=5GB')
        self.assertTrue(result, '执行失败' + text)

        text = '-----step3:重启; expect:执行成功-----'
        self.log.info(text)
        restart_res = self.s1_comsh.restart_db_cluster()
        self.log.info(restart_res)
        self.assertTrue(restart_res, '执行失败' + text)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        text = '-----step4:检验参数; expect:执行成功-----'
        self.log.info(text)
        result_param = self.common.show_param(self.recovery_parse_workers)
        self.assertEquals(result_param, '2', '执行失败' + text)
        result_param = self.common.show_param(self.recovery_redo_workers)
        self.assertEquals(result_param, '2', '执行失败' + text)
        result_param = self.common.show_param(self.hot_standby)
        self.assertEquals(result_param, 'off', '执行失败' + text)
        result_param = self.common.show_param(self.ss_enable_ondemand_recovery)
        self.assertEquals(result_param, 'on', '执行失败' + text)
        result_param = self.common.show_param(self.ss_ondemand_recovery_mem_size)
        self.assertEquals(result_param, '5GB', '执行失败' + text)


        text = '-----step5:节点2 failover; expect:成功-----'
        self.log.info(text)
        stopdn = Primary_SH.exec_failover()
        self.log.info(stopdn)
        time.sleep(40)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        res1 = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        res2 = status.splitlines()[-1].split('|')[1].split('6002')[-1]
        res3 = status.splitlines()[-1].split('|')[2].split('6003')[-1]
        self.log.info(res1)
        self.log.info(res2)
        self.log.info(res3)
        self.assertIn('P Down    Manually stopped', res1, '执行失败' + text)
        self.assertTrue('S Primary Normal' in res2 or 'S Standby Normal' in res2,
                '执行失败' + text)
        self.assertTrue('S Primary Normal' in res3 or 'S Standby Normal' in res3,
                '执行失败' + text)

        text = '-----step6:查看集群状态; expect:集群状态Degraded-----'
        self.log.info(text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Degraded', status, '执行失败' + text)

        text = '-----step7:原节点进行节点启动; expect:执行成功-----'
        self.log.info(text)
        startdn = Primary_SH.exec_cm_ctl('start')
        self.log.info(startdn)
        self.assertIn(self.constant.cm_start_success_msg, startdn,
                '拉起dn节点失败')

        text = '-----step8:查看集群状态; expect:状态正常-----'
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)
        res1 = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        self.log.info(res1)
        self.assertIn('     P Standby Normal ', res1, '执行失败' + text)

        text = '-----step9:ondemand参数回复初始状态; expect:执行成功-----'
        self.log.info(text)

        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.recovery_parse_workers}={self.recovery_parse_workers_default}')
        self.assertTrue(result, '执行失败' + text)
        self.log.info(text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.recovery_redo_workers}={self.recovery_redo_workers_default}')
        self.assertTrue(result, '执行失败' + text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.hot_standby}={self.hot_standby_default}')
        self.assertTrue(result, '执行失败' + text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.ss_enable_ondemand_recovery}={self.ss_enable_ondemand_recovery_default}')
        self.assertTrue(result, '执行失败' + text)
        result = self.s1_comsh.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'{self.ss_ondemand_recovery_mem_size}={self.ss_ondemand_recovery_mem_size_default}')
        self.assertTrue(result, '执行失败' + text)

        text = '-----step10:集群停止; expect:执行成功-----'
        self.log.info(text)
        stopdn = Primary_SH.exec_cm_ctl('stop')
        self.log.info(stopdn)
        self.assertIn(self.constant.cm_stop_success_msg, stopdn,
                '停止dn节点失败')
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.assertIn("can't connect to cm_server", status, '执行失败' + text)
        res1 = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        self.log.info(res1)
        self.assertIn("Maybe cm_server is not running, or timeout expired. Please try again.", res1, '执行失败' + text)

        text = '-----step11:原节点进行节点启动; expect:执行成功-----'
        self.log.info(text)
        startdn = Primary_SH.exec_cm_ctl('start')
        self.log.info(startdn)
        self.assertIn(self.constant.cm_start_success_msg, startdn,
                '拉起dn节点失败')
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)

        text = '-----step12:参数为初始状态; expect:成功-----'
        result_param = self.common.show_param(self.recovery_parse_workers)
        self.assertEquals(result_param, self.recovery_parse_workers_default, '执行失败' + text)
        result_param = self.common.show_param(self.recovery_redo_workers)
        self.assertEquals(result_param, self.recovery_redo_workers_default, '执行失败' + text)
        result_param = self.common.show_param(self.hot_standby)
        self.assertEquals(result_param, self.hot_standby_default, '执行失败' + text)
        result_param = self.common.show_param(self.ss_enable_ondemand_recovery)
        self.assertEquals(result_param, self.ss_enable_ondemand_recovery_default, '执行失败' + text)
        result_param = self.common.show_param(self.ss_ondemand_recovery_mem_size)
        self.assertEquals(result_param, self.ss_ondemand_recovery_mem_size_default, '执行失败' + text)

    def tearDown(self):
        text = '-----step13:重启; expect:执行成功-----'
        self.log.info(text)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        status = Primary_SH.check_cluster_core_status(status, wait_times=600)
        self.log.info(status)
        restart_res = self.s1_comsh.restart_db_cluster()
        self.assertTrue(restart_res, '执行失败' + text)

        stopdn = Primary_SH.exec_cm_ctl('stop')
        self.log.info(stopdn)
        self.assertIn(self.constant.cm_stop_success_msg, stopdn,
                '停止dn节点失败')
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.assertIn("can't connect to cm_server", status, '执行失败' + text)

        startdn = Primary_SH.exec_cm_ctl('start')
        self.log.info(startdn)
        self.assertIn(self.constant.cm_start_success_msg, startdn,
                '拉起dn节点失败')
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)

        text = '-----step14:恢复环境为初始集群状态; expect:成功-----'
        self.log.info(text)
        recovery = Primary_SH.exec_cm_ctl(mode='switchover', param='-a')
        self.log.info(recovery)
        self.assertIn(self.constant.cm_switchover_success_msg, recovery,
                      '执行失败' + text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('P Primary Normal',
                      status.splitlines()[-1].split('|')[0].split('6001')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                      status.splitlines()[-1].split('|')[1].split('6002')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                    status.splitlines()[-1].split('|')[2].split('6003')[-1],
                    '执行失败' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
